﻿#region

using System;
using System.Net.Sockets;
using System.Threading;
using log4net;

#endregion

namespace Jiubang.Communication.Server{
    public sealed class SocketAsyncHelper{
        private static CommonServer commonServer;
        private readonly bool isCompleteAsync;
        private readonly ILog log = LogManager.GetLogger(typeof (SocketAsyncHelper));
        private readonly WaitCallback ioCallBack;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="isCompleteAsync">Socket异步方法执行返回false时根据本参数值决定是否异步执行回调方法</param>
        /// <param name="server"></param>
        public SocketAsyncHelper(bool isCompleteAsync, CommonServer server){
            this.isCompleteAsync = isCompleteAsync;
            commonServer = server;
            ioCallBack = IoCompleted;
        }

        /// <summary>
        /// Socket异步方法执行处理。
        /// 如果Socket异步方法执行返回false，则根据设置规则决定是否异步执行回调操作。
        /// </summary>
        /// <param name="act"></param>
        /// <param name="e"></param>
        internal void AsyncMethodHelper(CommonServer.AsyncMethod act, SocketAsyncEventArgs e){
            switch (act){
                case CommonServer.AsyncMethod.SendAsync:
                    //e.AcceptSocket.SendAsync(e)同步完成返回false，此时要手动调用ioCallBack
                    if (e.AcceptSocket.SendAsync(e)) return;
                    if (isCompleteAsync) ThreadPool.QueueUserWorkItem(ioCallBack, e);
                    else ioCallBack(e);
                    break;
                case CommonServer.AsyncMethod.ReceiveAsync:
                    if (e.AcceptSocket.ReceiveAsync(e)) return;
                    if (isCompleteAsync) ThreadPool.QueueUserWorkItem(ioCallBack, e);
                    else ioCallBack(e);
                    break;
                default:
                    if (commonServer.listenerSocket.AcceptAsync(e)) return;
                    if (isCompleteAsync) ThreadPool.QueueUserWorkItem(AcceptCompleted,e);
                    else AcceptCompleted(e);
                    break;
            }
        }

        private void AcceptCompleted(object e){
            try{
                commonServer.AcceptCompleted(commonServer, e as SocketAsyncEventArgs);
            } catch (Exception exception){
                log.Error(exception);
            }
        }

        private void IoCompleted(object args){
            try{
                commonServer.IoCompleted(commonServer, args as SocketAsyncEventArgs);
            } catch (Exception exception){
                log.Error(exception);
            }
        }

        #region Nested type: SocketAsyncMethod

        internal delegate bool SocketAsyncMethod(SocketAsyncEventArgs args);

        #endregion
    }
}